#include "gdbTask.h"

#include <adapter/qtRbbSerial.h>
#include <mopenocd.h>
#include <gdbio/qtRioNet.h>

using namespace mopenocd;

static void loghandler(void *ctx, const char *fmt, ...)
{
    gdbTask *gdb = static_cast<gdbTask*>(ctx);
    QString str;
    va_list va;

    va_start(va, fmt);
    str = str.vsprintf(fmt, va);
    va_end(va);

    emit gdb->outLog(str);
}

static void gdblog(void *ctx, const char *fmt, ...)
{
    QString str;
    va_list va;

    va_start(va, fmt);
    str = str.vsprintf(fmt, va);
    va_end(va);
    qDebug(str.toStdString().c_str());
}

gdbTask::gdbTask()
{

}

gdbTask::~gdbTask()
{
    isrun = false;
    terminate();
    wait(5000);
}

void gdbTask::run()
{
    qtRbbSerial ad;
    jtag_tap tap;
    targetRISCV ta;
    gdbRDP gdb;
    qtServerIO sio;
    gdbPacket pbuf;
    QString str;
    int ret;
    QString comname, combd;

    loghandler(this, "gdbServer started");

    if (pbuf.bufsz() == 0)
    {
        loghandler(this, "fail init buf\n");
        return;
    }

    comname = taskTest::params.split(":").first();
    combd = taskTest::params.split(":").last();

    if (!ad.open(comname.toStdString().c_str(), combd.toUInt()))
    {
        loghandler(this, "fail open com\n");
        return;
    }

    loghandler(this, "open serial success");

    tap.bind(&ad);
    tap.init();
    tap.jtag_init_inner();

    loghandler(this, "idcode: %x", tap.idCode());

    ta.setLogger(this, loghandler);
    ta.bind(&tap);
    ta.init();

    loghandler(this, "waiting for target");

    while (isrun)
    {
        ret = ta.examine();
        if (ret == 0)
            break;

        msleep(100);
    }

    if (ret == 0)
    {
        loghandler(this, "examine success");
        ta.halt();
        ta.pollCurStatus();
    }

    gdb.setLogger(this, gdblog);

waitgdb:
    loghandler(this, "waiting for gdb");
    if (sio.open("localhost", 2331) != 0)
    {
        qDebug("new tcpserver fail\n");
        return;
    }

    loghandler(this, "gdb conncted");

    while (isrun)
    {
        if (!ta.examined())
        {
            ta.examine();
        }

        ret = gdb.loop(sio, ta, pbuf);
        if (ret < 0)
        {
            loghandler(this, "gdb disconncted");
            sio.close();
            goto waitgdb;
        }
    }

    qDebug("gdbServer exit");
}
